﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.Net.Mime;
using System.Security.Cryptography;
using eWallet.Security.Cryptography;

namespace eWallet.Data.Local
{
	public partial class eWalletDataSet
	{
		public partial class SecretsDataTable
		{

			public SecretsRow AddSecretsRow(string description, string data, GroupsRow group, ICryptoModule groupCryptoModule)
			{
				return this.AddSecretsRow(description, Encoding.UTF8.GetBytes(data), group, groupCryptoModule);
			}

			public SecretsRow AddSecretsRow(string description, byte[] data, GroupsRow group, ICryptoModule groupCryptoModule)
			{
				if (null == group)
					throw new ArgumentNullException("group");

				var alg = group.DecryptGroupKeyAlgorithm(groupCryptoModule);
				byte[] cipher = new SymmetricKeyCryptoModule(alg).Encrypt(data);

				eWalletDataSet ds = (eWalletDataSet)this.DataSet;
				BlobsRow blobRow =  ds.Blobs.AddBlobsRow(Guid.NewGuid(), cipher);
				return this.AddSecretsRow(description, group, blobRow);
			}

			public SecretsRow AddSecretsRow(string description, GroupsRow group, BlobsRow encryptedSecret)
			{
				return this.AddSecretsRow(
					Guid.NewGuid(),
					DateTime.UtcNow,
					string.Format(@"{0}\{1}", Environment.UserDomainName, Environment.UserName),
					group,
					description,
					MediaTypeNames.Text.Plain,
					null,
					encryptedSecret
				);
			}

			public SecretsRow NewSecretsRow(Guid id)
			{
				SecretsRow row = this.NewSecretsRow();
				row.Id = id;
				row.LastModified = DateTime.UtcNow;
				row.LastModifiedBy = string.Format(@"{0}\{1}", Environment.UserDomainName, Environment.UserName);
				row.ContentType = System.Net.Mime.MediaTypeNames.Text.Plain;
				row.SetFileNameNull();
				return row;
			}

			/// <summary>
			/// Returns an array of secrets that are tagged with the given tags.
			/// </summary>
			/// <param name="tags">An array of tags that the returned secrets must be tagged with.</param>
			public IEnumerable<SecretsRow> Select(IEnumerable<TagsRow> tags)
			{
				foreach (var item in this)
				{
					if (item.IsTaggedWith(tags))
					{
						yield return item;
					}
				}
			}

			public IEnumerable<SecretsRow> Select(IEnumerable<SecretsTagsRow> tags)
			{

				foreach (var secret in this)
				{
					if (null == tags || null != tags.FirstOrDefault(t => t.SecretId == secret.Id))
					{
						yield return secret;
					}
				}

			}
		}
	}
}
